package co.yixiang.yshop.module.order.handle;

import cn.hutool.core.thread.ExecutorBuilder;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.constant.ShopConstants;
import co.yixiang.yshop.framework.common.enums.OrderDefaultRuleEnum;
import co.yixiang.yshop.module.order.service.storeaftersales.StoreAfterSalesService;
import co.yixiang.yshop.module.order.service.storeorder.AppStoreOrderService;
import co.yixiang.yshop.module.order.service.storeorder.StoreOrderService;
import co.yixiang.yshop.module.product.service.campaigninfo.CampaignInfoService;
import co.yixiang.yshop.module.shop.service.popup.PopupService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;

/**
 * 延时队列消费
 *
 * @author hupeng
 * @date 2023.7.27
 */
@Component
@Slf4j
public class RedisDelayHandle {
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private AppStoreOrderService appStoreOrderService;

    @Resource
    private StoreAfterSalesService storeAfterSalesService;
    @Resource
    private CampaignInfoService campaignInfoService;
    @Resource
    private PopupService popupService;

    @Resource
    private StoreOrderService storeOrderService;


    @PostConstruct
    public void startJobTimer() {
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNamePrefix("delay-job-service").build();
        log.info("========延时队列开始=========");
        ExecutorService executorService = ExecutorBuilder.create()
                .setCorePoolSize(8)
                .setMaxPoolSize(12)
                .setKeepAliveTime(0)
                .setThreadFactory(threadFactory)
                .build();

        executorService.execute(new ExecutorTaskUnPay());
        executorService.execute(new ExecutorTaskUnConfirm());
        executorService.execute(new ExecutorTaskAfterSalesConfirm());
        executorService.execute(new ExecutorTaskAfterSalesUserReturnGoods());
        executorService.execute(new ExecutorTaskCampaign());
        executorService.execute(new ExecutorTaskPopup());
        executorService.execute(new ExecutorTaskTeamwork());
        executorService.execute(new ExecutorCloseAfterSale());
    }

    class ExecutorTaskUnPay implements Runnable {
        @SneakyThrows
        @Override
        public void run() {
            RBlockingDeque<String> blockingUnPayDeque = redissonClient
                    .getBlockingDeque(OrderDefaultRuleEnum.ORDER_OUTTIME_UNPAY.getKey());
            redissonClient.getDelayedQueue(blockingUnPayDeque);
            while (true) {
                try {
                    log.info("======延时取消订单循环任务=====");
                    String unPayOrderId = blockingUnPayDeque.take();
                    log.info("获取到未付款订单id：{}", unPayOrderId);
                    if (StrUtil.isNotEmpty(unPayOrderId)) {
                        appStoreOrderService.cancelOrder(unPayOrderId, null);
                    }
                } catch (Exception e) {
                    log.error("延时取消订单消费失败，" + e.getMessage());
                }
            }
        }
    }

    class ExecutorTaskUnConfirm implements Runnable {
        @SneakyThrows
        @Override
        public void run() {
            RBlockingDeque<String> blockingUnConfirmDeque = redissonClient
                    .getBlockingDeque(OrderDefaultRuleEnum.ORDER_OUTTIME_UNCONFIRM.getKey());
            redissonClient.getDelayedQueue(blockingUnConfirmDeque);
            while (true) {
                log.info("======延时确认收货循环任务（自动确认订单收货）=====");
                String unConfirmOrderId = "";
                try {
                    unConfirmOrderId = blockingUnConfirmDeque.take();
                    log.info("获取到待确认收货订单id：{}", unConfirmOrderId);
                    if (StrUtil.isNotEmpty(unConfirmOrderId)) {
                        appStoreOrderService.takeOrder(unConfirmOrderId, null,"admin");
                    }
                } catch (Exception e) {
                    log.error("延时确认收货失败，" + e.getMessage());
                }
            }
        }
    }

    class ExecutorTaskAfterSalesConfirm implements Runnable {
        @SneakyThrows
        @Override
        public void run() {
            RBlockingDeque<Long> blockingUnConfirmDeque = redissonClient
                    .getBlockingDeque(OrderDefaultRuleEnum.AFTER_SALES_ORDER_OUTTIME_UNCONFIRM.getKey());
            redissonClient.getDelayedQueue(blockingUnConfirmDeque);
            while (true) {
                log.info("======延时售后用户确认收货循环任务(通过用户的售后请求)=====");
                Long unConfirmOrderId;
                try {
                    unConfirmOrderId = blockingUnConfirmDeque.take();
                    log.info("获取到待确认售后用户收货订单id：{}", unConfirmOrderId);
                    storeAfterSalesService.taskAfterSalesConfirm(unConfirmOrderId);
                } catch (Exception e) {
                    log.error("延时确认售后用户收货失败，" + e.getMessage());
                }
            }
        }
    }
    class ExecutorTaskAfterSalesUserReturnGoods implements Runnable {
        @SneakyThrows
        @Override
        public void run() {
            RBlockingDeque<Long> blockingUnConfirmDeque = redissonClient
                    .getBlockingDeque(OrderDefaultRuleEnum.AFTER_SALES_ORDER_USER_NO_RETURN_GOODS.getKey());
            redissonClient.getDelayedQueue(blockingUnConfirmDeque);
            while (true) {
                log.info("======延时操作：检查用户售后请求有没有正常操作（填写退货物流）=====");
                Long unConfirmOrderId;
                try {
                    unConfirmOrderId = blockingUnConfirmDeque.take();
                    log.info("检查售后订单填写退货物流的情况：{}", unConfirmOrderId);
                    storeAfterSalesService.taskAfterSalesCancel(unConfirmOrderId);
                } catch (Exception e) {
                    log.error("检查售后订单填写退货物流的情况，" + e.getMessage());
                }
            }
        }
    }

    class ExecutorTaskCampaign implements Runnable {
        @SneakyThrows
        @Override
        public void run() {
            RBlockingDeque<Long> blockingCampaignDeque = redissonClient.getBlockingDeque(ShopConstants.CAMPAIGN_CHANGE);
            redissonClient.getDelayedQueue(blockingCampaignDeque);
            while (true) {
                log.info("======延时营销活动循环任务=====");
                Long id;
                try {
                    id = blockingCampaignDeque.take();
                    log.info("获取到营销活动id：{}", id);
                    campaignInfoService.campaignStateHandle(id);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("延时营销活动操作失败，" + e.getMessage());
                }
            }
        }
    }

    class ExecutorTaskPopup implements Runnable {
        @SneakyThrows
        @Override
        public void run() {
            RBlockingDeque<Long> blockingCampaignDeque = redissonClient.getBlockingDeque(ShopConstants.POPUP_CHANGE);
            redissonClient.getDelayedQueue(blockingCampaignDeque);
            while (true) {
                log.info("======延时广告弹窗循环任务=====");
                Long id;
                try {
                    id = blockingCampaignDeque.take();
                    log.info("获取到广告弹窗id：{}", id);
                    popupService.stateChange(id);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("延时广告弹窗操作失败，" + e.getMessage());
                }
            }
        }
    }

    class ExecutorTaskTeamwork implements Runnable {
        @SneakyThrows
        @Override
        public void run() {
            RBlockingDeque<Long> blockingCampaignDeque = redissonClient.getBlockingDeque(ShopConstants.TEAMWORK_CHANGE);
            redissonClient.getDelayedQueue(blockingCampaignDeque);
            while (true) {
                log.info("======延时拼团循环任务=====");
                Long id;
                try {
                    id = blockingCampaignDeque.take();
                    log.info("获取到拼团id：{}", id);
                    // 拼团结束
                    appStoreOrderService.teamworkEnd(id);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("延时拼团操作失败，" + e.getMessage());
                }
            }
        }
    }

    class ExecutorCloseAfterSale implements Runnable {

        @Override
        public void run() {
            RBlockingDeque<Long> blockingDeque = redissonClient
                    .getBlockingDeque(OrderDefaultRuleEnum.ORDER_MAX_CAN_AFTER_SALE_TIME.getKey());
            redissonClient.getDelayedQueue(blockingDeque);
            while (true) {
                log.info("======延时关闭订单售后任务=====");
                Long id;
                try {
                    id = blockingDeque.take();
                    storeOrderService.closeAfterSaleOrder(id);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("延时关闭订单售后任务，" + e.getMessage());
                }
            }
        }
    }

}
